/*******************************************************************************
 * @file    bsp_pwm.c
 * @author  Harm
 * @version V1.00
 * @date    17-May-2022
 * @brief   ......
*******************************************************************************/


/* Define to prevent recursive inclusion -------------------------------------*/
#define __BSP_PWM_C__


/* Includes ------------------------------------------------------------------*/
#include "bsp_pwm.h"


/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/


/* Private variables ---------------------------------------------------------*/



#if PWM_ENABLE

/* Private function prototypes -----------------------------------------------*/
static void Tim3GpioInit(void);
static void Tim3ModeInit(void);
/* Private functions ---------------------------------------------------------*/


/* Exported variables --------------------------------------------------------*/
/* Exported function prototypes ----------------------------------------------*/




/*******************************************************************************
 * @brief       
 * @param       
 * @retval      
 * @attention   
*******************************************************************************/
void PWM_Init(void)//Timer3 配置为输出比较模式，产生两个通道的PWM波
{
	Tim3GpioInit();
	Tim3ModeInit();		
}


/*******************************************************************************
 * @brief       
 * @param       
 * @retval      
 * @attention   
*******************************************************************************/
//演示PWM功能
static void Tim3GpioInit(void) 
{
	GPIO_InitTypeDef GPIO_InitStructure;

  // 输出比较通道1 GPIO 初始化
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);//复用功能时钟开启
	GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE);//IO完全重映射使能。将TIM3_CH1、TIM3_CH2分别复用值PC6、PC7.未开启时默认为PA6 PA7
	
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6;  //CH1
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOC, &GPIO_InitStructure);
	
	// 输出比较通道2 GPIO 初始化
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_7;//CH2
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOC, &GPIO_InitStructure);
	
}

/*******************************************************************************
 * @brief       
 * @param       
 * @retval      
 * @attention   
*******************************************************************************/
///*
// * 注意：TIM_TimeBaseInitTypeDef结构体里面有5个成员，TIM6和TIM7的寄存器里面只有
// * TIM_Prescaler和TIM_Period，所以使用TIM6和TIM7的时候只需初始化这两个成员即可，
// * 另外三个成员是通用定时器和高级定时器才有.
// *-----------------------------------------------------------------------------
// *typedef struct
// *{ TIM_Prescaler            都有
// *	TIM_CounterMode			     TIMx,x[6,7]没有，其他都有
// *  TIM_Period               都有
// *  TIM_ClockDivision        TIMx,x[6,7]没有，其他都有
// *  TIM_RepetitionCounter    TIMx,x[1,8,15,16,17]才有
// *}TIM_TimeBaseInitTypeDef; 
// *-----------------------------------------------------------------------------
// */

/* ----------------   PWM信号 周期和占空比的计算--------------- */
// ARR ：自动重装载寄存器的值
// CLK_cnt：计数器的时钟，等于 Fck_int / (psc+1) = 72M/(psc+1)
// PWM 信号的周期 T = (ARR+1) * (1/CLK_cnt) = (ARR+1)*(PSC+1) / 72M
// 占空比P=CCR/(ARR+1)
//C99 标准编译 请勾选 option for target->c/c++->C99 mode
static void Tim3ModeInit(void)
{
  // 开启定时器时钟,即内部时钟CK_INT=72M
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
	
	TIM_DeInit(TIM3);										//重新将Timer设置为缺省值
	TIM_InternalClockConfig(TIM3);							//采用内部时钟给TIM3提供时钟源
	
/*--------------------时基结构体初始化-------------------------*/
	// 配置周期，这里配置为10K,根据具体频率更改宏定义GENERAL_TIM3_Period、GENERAL_TIM3_Prescaler值
	
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	// 自动重装载寄存器的值，累计TIM_Period+1个频率后产生一个更新或者中断
	TIM_TimeBaseStructure.TIM_Period=GENERAL_TIM3_Period-1;	
	// 驱动CNT计数器的时钟 = Fck_int/(psc+1)
	TIM_TimeBaseStructure.TIM_Prescaler= GENERAL_TIM3_Prescaler-1;	
	// 时钟分频因子 ，配置死区时间时需要用到
	TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;		
	// 计数器计数模式，设置为向上计数
	TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;		
	// 重复计数器的值，没用到不用管
	TIM_TimeBaseStructure.TIM_RepetitionCounter=0;	
	// 初始化定时器
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

	/*--------------------输出比较结构体初始化-------------------*/	
	// 占空比配置
	uint16_t CCR1_Val = 50;
	uint16_t CCR2_Val = 40;

	TIM_OCInitTypeDef  TIM_OCInitStructure;
	// 配置为PWM模式1
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	// 输出使能
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	// 输出通道电平极性配置	
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//TIM_OCMode_PWM1模式下，小于CCR值为输出高电平
	
	// 输出比较通道 1
	TIM_OCInitStructure.TIM_Pulse = CCR1_Val;
	TIM_OC1Init(TIM3, &TIM_OCInitStructure);
	TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
	
	// 输出比较通道 2
	TIM_OCInitStructure.TIM_Pulse = CCR2_Val;
	TIM_OC2Init(TIM3, &TIM_OCInitStructure);
	TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);
	
	// 使能计数器
	TIM_Cmd(TIM3, ENABLE);
}


/*******************************************************************************
 * @brief       
 * @param       
 * @retval      
 * @attention   
*******************************************************************************/
void shell_PWM_Test_cmd(char argc, char *argv)
{
	uint8_t ch;
	uint8_t duty;
	char *param;
	
	if(argc<3)
	{
		printf("Error Command! Usage (such as):pwm ch duty (ch:1 or 2)(duty:0~100)\r\n");
		goto END;
	}
	
	param = &(argv[argv[1]]);
	ch = atoi(param);
	
	if(ch<1 || ch > 2)
	{
		printf("Error Command! Usage (such as):pwm ch duty (ch:1 or 2)(duty:0~100)\r\n");
		goto END;
	}
	
	param = &(argv[argv[2]]);
	duty = atoi(param);
	
	if(duty > 100)
	{
		printf("Error Command! Usage (such as):pwm ch duty (ch:1 or 2)(duty:0~100)\r\n");
		goto END;
	}
	
	if(ch == 1)
	{
		TIM_SetCompare1(TIM3, duty%100);
	}
	else if(ch == 2)
	{
		TIM_SetCompare2(TIM3, duty%100);
	}	
END:
		;
} 



#endif


/******************* (C) COPYRIGHT 2022 END OF FILE****************************/

